import { ref, reactive, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'

function isNumber(val: string | null) {
  if (!val) return false
  return /^\d+$/.test(val)
}

/**
 * 将query参数 数字的字符串 转为 number类型
 */
function formatQuery(data: Record<string, string | null>) {
  const query: Record<string, unknown> = Object.create(null)

  for (const [key, val] of Object.entries(data)) {
    query[key] = isNumber(val) ? Number(val) : val
  }

  return query
}

interface PageOption<P, R> {
  request(param?: P): Promise<ResponseList<R>>
  /** 是否立获取数据 默认true */
  immediate?: boolean
  /** 翻页时是否 replace 路由(携带query参数) 默认 true */
  route?: boolean
}

export function usePage<R extends RequestPagination, D, F>(opt: PageOption<R, D>, form: F) {
  const searchFields: Record<string, any> = Object.create(null)

  const options = { immediate: true, route: true, ...opt }

  function updateFields<F extends RequestPagination>(form: F, pagination: { current: number; limit: number }) {
    searchFields.pageNum = pagination.current
    searchFields.pageSize = pagination.limit

    for (const [key, value] of Object.entries(form)) {
      searchFields[key] = value
    }
  }

  function resetFields() {
    Object.keys(searchFields).forEach(key => {
      delete searchFields[key]
    })
  }

  /**
   * 当第一次进入页面后 如果发现 url 携带 `pageNum` `pageSize`
   *
   * 请求数据完毕后会手动更新分页数据
   *
   * 分页使用了 watch 监听 触发 search
   *
   * 默认 true 阻止 触发 search
   */
  const breakSearch = ref(false)

  const pagination = reactive({
    limit: 10,
    current: 1,
    total: 0
  })

  const table: DataTable<D> = reactive({
    loading: false,
    data: [],
    resData: {}
  })

  const route = useRoute()
  const router = useRouter()

  async function _fetchData(params?: RequestPagination) {
    if (options.route) {
      const query = formatQuery(route.query as Record<string, string | null>)
      console.log('diff', searchFields, query, JSON.stringify(searchFields) === JSON.stringify(query))
      if (JSON.stringify(searchFields) !== JSON.stringify(query)) {
        router.replace({ query: searchFields })
      }
    }

    table.loading = true

    try {
      const { list, total } = await options.request({ ...params, ...searchFields } as R)
      table.data = list
      pagination.total = total
    } finally {
      table.loading = false
    }
  }

  function search(current?: number) {
    if (current !== undefined) {
      const params: RequestPagination = {
        pageSize: pagination.limit,
        pageNum: pagination.current
      }

      updateFields(form, pagination)
      _fetchData(params)
      return
    }

    if (pagination.current === 1) {
      search(1)
      return
    }

    pagination.current = 1
  }

  function resetForm(form: HTMLFormElement) {
    form.reset()

    resetFields()
    router.replace(route.path)
  }

  watch(
    () => pagination.current,
    val => {
      if (breakSearch.value) return
      search(val)
    }
  )

  watch(
    () => pagination.limit,
    val => {
      if (breakSearch.value) return

      console.log(Math.ceil(pagination.total / val), pagination.current)
      /**
       * 当前总数 / 新分页条数 = 修改后最大页码
       * 如果小于 当前页码
       * 说明 当前页码需要更新为 修改后最大页码
       * 取消获取数据请求
       * 页码更新
       */
      if (Math.ceil(pagination.total / val) < pagination.current) return
      search(pagination.current)
    }
  )

  return {
    table,
    resetForm,
    search
  }
}
